﻿using System;
using System.Collections.Generic;
using System.Linq;
using CncConvProg.Model.FileManageUtility;

namespace CncConvProg.Model.ConversationalStructure.Abstraction
{
    [Serializable]
    public abstract class FaseDiLavoro : IEquatable<FaseDiLavoro>
    {
        #region Time Stuff

        #region Time Calculation Stuff

        /// <summary>
        /// Tempo medio programmazione operazione 
        /// Espresso in minuti
        /// </summary>
        public int AverageProgrammingOperationTime { get; set; }

        /// <summary>
        /// Tempo medio preparazione staffaggio.
        /// Espresso in minuti
        /// </summary>
        public int AverageSetupFixtureTime { get; set; }

        /// <summary>
        /// Tempo Medio Montaggio Utensile
        /// Espresso in minuti
        /// </summary>
        public int AverageMountingToolTime { get; set; }

        /// <summary>
        /// Tempo Default Caricamento Pezzo
        /// Espresso in secondi
        /// </summary>
        public int MachineLoadingTime { get; set; }

        #endregion

        #endregion

        public abstract TipoFaseLavoro TipoFase { get; }
        public enum TipoFaseLavoro
        {
            Centro,
            Tornio2Assi,
            Tornio3Assi
        }

        public Guid FaseDiLavoroGuid { get; private set; }

        public Guid MachineGuid { get; set; }

        public double LimitatoreTornio { get; set; }

        public DateTime CreationTime { get; set; }

        public string Descrizione { get; set; }

        protected FaseDiLavoro()
        {
            FaseDiLavoroGuid = Guid.NewGuid();
            IsValid = true;
        }

        public bool Equals(FaseDiLavoro other)
        {
            return other.FaseDiLavoroGuid == FaseDiLavoroGuid;
        }

        /// <summary>
        /// Restituisce porta utensile.
        /// Non lo implemento nella classe macchina perchè potrebbe non essere selezionata
        /// </summary>
        /// <returns></returns>

        public bool IsValid { get; set; }

        public IEnumerable<Lavorazione> Lavorazioni
        {
            get
            {
                return Singleton.Instance.GetLavorazioni(FaseDiLavoroGuid);
            }
        }
        public void UpdateValidFlag()
        {
            IsValid = Lavorazioni.All(p => p.IsValid);
        }

        public ToolMachine.ToolMachine GetMacchina()
        {
            var machines = PathFolderHelper.GetToolMachines();

            return machines.Where(m => m.MachineGuid == MachineGuid).FirstOrDefault();
        }

        public double NoChangeToolSecureZ { get; set; }

        public void ResetLavorazioniNumeration()
        {
            var index = 1;
            var lavs = this.Lavorazioni;

            foreach (var l in lavs)
            {
                l.LavorazionePosition = index;
                index++;
            }
        }


        public void AddLavorazione(Lavorazione lavorazione)
        {
            var prevFase = lavorazione.FaseDiLavoro;

            lavorazione.ResetFaseDiLavoro(this.FaseDiLavoroGuid);

            if (prevFase != null && prevFase.FaseDiLavoroGuid != FaseDiLavoroGuid)
                prevFase.ResetLavorazioniNumeration();

            //Riaggiorno valid flag
            UpdateValidFlag();

        }

        public bool IsCompatible(Lavorazione lavorazione)
        {
            return lavorazione.FasiCompatibili.Contains(TipoFase);
        }

        /// <summary>
        /// Ritorna il valore più basso fra limitatore giri macchina e quello settato
        /// </summary>
        /// <returns></returns>
        internal double GetLimitatoreGiri(ToolMachine.ToolMachine macchina)
        {
            var lM = 0.0d;
            if (macchina != null)
                lM = macchina.MaxGiri;

            if (LimitatoreTornio <= 0 && lM > 0)
                return lM;

            if (LimitatoreTornio > 0 && lM <= 0)
                return LimitatoreTornio;

            if (LimitatoreTornio > 0 && lM > 0)
                return Math.Min(LimitatoreTornio, lM);

            return 0;
        }

        internal double GetRapidFeed()
        {
            var macchina = Singleton.Data.GetMacchina(MachineGuid);

            if (macchina != null)
                return macchina.VelocitaRapido;

            return 10000;
        }
    }
}